# -*- coding: utf-8 -*-
import logging

from common import orm
from common.mch import handler as mch_handler
from common.timer import TIMER_EVENT_TYPE, TimerEvent, EventHandler
from common.utils import tz
from common.withdraw import handler as withdraw_handler

_LOGGER = logging.getLogger(__name__)


def submit_notify_event(pay):
    event_msg = {'pay_id': pay.id}
    expire_ts = tz.now_ts()
    TimerEvent.submit(TIMER_EVENT_TYPE.MCH_NOTIFY, event_msg, expire_ts)
    _LOGGER.info(
        'start timer to notify pay %s event in %s seconds later.', pay.id, expire_ts)


class MchNotifyHandler(EventHandler):
    MAX_TRY = 13

    def process(self, event_msg):
        _LOGGER.info('mch notify Event [%s]' % event_msg)
        try:
            pay_id = event_msg['pay_id']
            # notify
            _LOGGER.info('to process notify_mch, pay[%s]', pay_id)
            success, _ = mch_handler.notify_mch(pay_id)
            if success:
                _LOGGER.info('pay notified success %s' % event_msg)
                return True
            else:
                _LOGGER.info('pay notified fail %s' % event_msg)
                return False
        except Exception as e:
            orm.session.rollback()
            _LOGGER.exception('MchNotifyHandler process error.(%s)' % e)
            return False
        finally:
            orm.session.close()


def _calc_delay_notify_withdraw_ts(withdraw):
    """
    采用退避重发机制 15/15/30/180/1800/1800/1800/1800/3600/3600/...
    最长24小时
    """
    withdraw_ts = tz.to_ts(withdraw.withdraw_at)
    if tz.now_ts() - withdraw_ts > 24 * 3600:
        _LOGGER.warn('withdraw[%s] notify has expired in 24 hours!', withdraw.id)
        return None
    if withdraw.notify_count <= 2:
        return 15
    if withdraw.notify_count == 3:
        return 30
    if withdraw.notify_count == 4:
        return 180
    if withdraw.notify_count <= 8:
        return 1800
    return 3600


def submit_notify_withdraw_event(order):
    event_msg = {'withdraw_id': order.id}
    delay_ts = _calc_delay_notify_withdraw_ts(order)
    if not delay_ts:
        return
    expire_ts = tz.now_ts() + delay_ts
    TimerEvent.submit(TIMER_EVENT_TYPE.WITHDRAW_NOTIFY, event_msg, expire_ts)
    _LOGGER.info(
        'start timer to notify withdraw event in %s seconds later.', delay_ts)


class WithdrawNotifyHandler(EventHandler):
    MAX_TRY = 13

    def process(self, event_msg):
        _LOGGER.info('mch notify Event [%s]' % event_msg)
        try:
            withdraw_id = event_msg['withdraw_id']
            # notify
            _LOGGER.info('to process notify_mch, withdraw[%s]', withdraw_id)
            success, withdraw = withdraw_handler.notify_mch(withdraw_id)
            if success:
                _LOGGER.info('withdraw notified success %s' % event_msg)
                return True
            else:
                _LOGGER.info('withdraw notified fail %s' % event_msg)
                return False
        except Exception as e:
            orm.session.rollback()
            _LOGGER.exception('MchNotifyHandler process error.(%s)' % e)
            return False
        finally:
            orm.session.close()
        return True
